package com.iwhalecloud.citybrain.flow.platform.manager.infrastructure.web;

import com.iwhalecloud.citybrain.flow.platform.manager.application.common.enums.TaskReadEnum;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.StringUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ErrorCode;
import com.iwhalecloud.citybrain.flow.platform.manager.common.ResponseResult;
import com.iwhalecloud.citybrain.flow.platform.manager.common.client.HttpTaskTakeBackDto;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowExecutionQueryInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowSpecifyTheNodeHandlerTaskQueryInfo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.FlowTaskCandidateDataTypeVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.User;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.form.ExternalFormQueryDTO;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.log.CommonOperateLogContentVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.log.CommonOperateLogForAddVo;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.model.NextNodeCandidateTaskDTO;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.task.*;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.user.UserMeta;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.task.api.Task;
import org.flowable.task.service.impl.persistence.entity.TaskEntityImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Controller - 任务
 *
 * @author lilh
 * @date 2019-01-23 14:10
 */
@RestController
@RequestMapping("/task")
@Api
public class FlowTaskController {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private TaskService taskService;

    @Autowired
    private FlowTaskService flowTaskService;

    @Autowired
    private FlowFormRepository flowFormRepository;

    @Autowired
    private FlowCommonOperateLogRepository flowCommonOperateLogRepository;

    @Autowired
    private FlowTaskQueryRepository flowTaskQueryRepository;

    @Autowired
    private FlowTaskTraceRepository flowTaskTraceRepository;

    @Autowired
    private FlowTaskEntrustService flowTaskEntrustService;

    @Autowired
    private   FlowTaskInstApproverRepository  flowTaskInstApproverRepository;

    /**
     * 待办列表
     */
    @ApiOperation(value = "获取代办任务列表")
    @PostMapping("/todo_list")
    public ResponseResult list(@RequestBody TaskQueryVo taskQueryVo) {
        User current = userRepository.getCurrentUser();
        if (Objects.isNull(current)) {
            return ResponseResult.fail(ErrorCode.NOT_EXIST.errCode(), "查询当前用户失败");
        }
        List<Task> tasks = taskService.createTaskQuery().taskCandidateOrAssigned(current.getUserCode()).active().list();
        List<TaskListVo> result = new ArrayList<>(tasks.size());
        for (Task task : tasks) {
            if (task instanceof TaskEntityImpl) {
                result.add(new TaskListVo((TaskEntityImpl) task));
            }
        }
        return ResponseResult.success(result);
    }

    /**
     * 任务表单
     */
    @ApiOperation(value = "获取任务表单")
    @PostMapping("/form")
    public ResponseResult form(@RequestBody @Validated TaskFormVo taskFormVo) {
        return ResponseResult.success(flowFormRepository.findTaskFormDetail(taskFormVo.getTaskId(), true));
    }

    /**
     * 办理任务
     */
    @ApiOperation(value = "处理任务（通过）")
    @PostMapping("/handle")
    public ResponseResult handle(@RequestBody TaskHandleVo taskHandleVo) {
        //如果为内置表单
        if(StringUtils.isEmpty(taskHandleVo.getFormId())){
            return flowTaskService.complete(taskHandleVo);
        }
        //如果为外置表单
        return ResponseResult.success(flowTaskService.completeWithExternalForm(taskHandleVo));
    }

    /**
     * 先签收，再完成任务
     */
    @ApiOperation(value = "处理任务")
    @PostMapping("/handleWithClaim")
    public ResponseResult handleWithClaim(@RequestBody TaskHandleVo taskHandleVo){
//        ResponseResult result = flowFormRepository.checkForcePickByForm(taskHandleVo.getTaskId());
//        if (!result.isSuccess()) {
//            logger.error("设置处理任务，强制选人功能检查发现问题：{}", result.getErrMsg());
//            return result;
//        }
        ExternalFormQueryDTO query= new ExternalFormQueryDTO();
        query.setTaskId(taskHandleVo.getTaskId());
        if(flowFormRepository.isExternalForm(query)){
            return flowTaskService.completeWithClaimAndExternalForm(taskHandleVo);
        }else{
            return flowTaskService.completeWithClaim(taskHandleVo);
        }
    }


    /**
     * 根据流程实例编号查询当前用户需要处理的taskId
     * @param processInstanceId
     * @return
     */
    @GetMapping("/getUserCurrentTask")
    public ResponseResult<TaskDTO> getUserCurrentTask(String processInstanceId){
        TaskDTO taskDTO = flowTaskService.getUserCurrentTask(processInstanceId);
        return ResponseResult.success(taskDTO);
    }





    /**
     * 保存任务表单填报数据
     *
     * @param taskHandleVo 填报数据
     * @return
     */
    @ApiOperation(value = "保存任务表单填报数据")
    @PostMapping("/saveFormDraft")
    public ResponseResult<Boolean> saveFormDraft(@RequestBody TaskHandleVo taskHandleVo) {
        return ResponseResult.success(flowTaskService.saveFormInstanceDraft(taskHandleVo));
    }

    private void appendHandleTaskLog(Task task, TaskHandleVo taskHandleVo, String errorMsg, String type) {
        CommonOperateLogContentVo content = new CommonOperateLogContentVo();
        content.setRequest(taskHandleVo);
        content.setResponse(errorMsg);
        CommonOperateLogForAddVo addVo = new CommonOperateLogForAddVo(task);
        if (Objects.isNull(task)) {
            addVo.setTaskId(taskHandleVo.getTaskId());
        }
        addVo.setType(type);
        flowCommonOperateLogRepository.insertOperateLog(addVo, content);

    }


    /**
     * 任务签收
     *
     * @param taskClaimVo
     * @return
     */
    @ApiOperation(value = "任务签收")
    @PostMapping("/claim")
    public ResponseResult claim(@RequestBody TaskClaimVo taskClaimVo) {
        return flowTaskService.claim(taskClaimVo);
    }

    /**
     * 任务转办
     *
     * @param turnTaskVo
     * @return
     */
    @ApiOperation(value = "任务转办")
    @PostMapping("/turnTask")
    public ResponseResult turnTask(@RequestBody @Validated TurnTaskVo turnTaskVo) {
        return flowTaskService.turnTask(turnTaskVo);
    }

    /**
     * 任务委托
     *
     * @param entrustTaskVo
     * @return
     */
    @ApiOperation(value = "任务委托")
    @PostMapping("/entrustTask")
    public ResponseResult entrustTask(@RequestBody @Validated EntrustTaskVo entrustTaskVo) {
        return flowTaskEntrustService.entrustTodoTask( entrustTaskVo);
    }


    @ApiOperation(value = "指定一下节点审批人")
    @PostMapping("/nextNodeAssignee")
    public ResponseResult appointNextNodeAssignee(@RequestBody NextNodeCandidateTaskDTO nextNodeCandidateTaskDTO){
        return flowTaskService.appointNextNodeCandidate(nextNodeCandidateTaskDTO);
    }

    @ApiOperation(value = "获取下一节点审批人配置的编码")
    @PostMapping("/nextNodeAssignParam")
    public ResponseResult getNextNodeAssignParam(@RequestBody BaseTaskVo baseTaskVo){
        return flowTaskService.getNextNodeAssgineeParam(baseTaskVo);
    }

    /**
     * 委派，将任务分配给其他人处理，处理完之后，还要回到当前任务
     * @param taskDelegateVo
     * @return
     */
    @ApiOperation(value = "委派")
    @PostMapping("/delegateTask")
    public ResponseResult delegateTask(@RequestBody @Validated TaskDelegateVo taskDelegateVo){
        return flowTaskService.delegateTask(taskDelegateVo);
    }



    /**
     * 任务加签
     *
     * @param addSignTaskVo
     * @return
     */
    @ApiOperation(value = "任务加签")
    @PostMapping("/addSignTask")
    public ResponseResult addSignTask(@RequestBody AddSignTaskVo addSignTaskVo) {
        return flowTaskService.addSignTask(addSignTaskVo);
    }

    /**
     * 任务拿回
     *
     * @param taskTakeBackDto
     * @return
     */
    @ApiOperation(value = "任务拿回")
    @PostMapping("/takeBack")
    public ResponseResult takeBack(@RequestBody HttpTaskTakeBackDto taskTakeBackDto) {
        return flowTaskService.takeBack(taskTakeBackDto);
    }


    /**
     * 根据任务编号查询当前节点会签的人员信息
     * @param baseTaskVo 任务信息
     * @return 当前节点加签的人员信息
     */
    @PostMapping("/getAssignee")
    public ResponseResult<List<UserMeta>> getAssignee(@RequestBody BaseTaskVo baseTaskVo){
        return flowTaskService.getAssignee(baseTaskVo);
    }

    /**
     * 减签，只能针对下一个节点进行减签操作
     * TODO 需求暂时不明确
     * @param deleteSignTaskVo
     * @return
     */
    public ResponseResult deleteSignTask(@RequestBody DeleteSignTaskVo deleteSignTaskVo){
        return flowTaskService.deleteSignTask(deleteSignTaskVo);
    }

    /**
     * 获取任务超时时间
     *
     * @param taskId
     * @return
     */
    @ApiOperation(value = "获取任务超时时间")
    @GetMapping("/getTaskTimeout")
    public ResponseResult getTaskTimeout(@RequestParam(value = "taskId") String taskId) {
        return flowTaskService.getTaskTimeout(taskId);
    }


    /**
     * 任务延期
     *
     * @param delayTaskVo
     * @return
     */
    @ApiOperation(value = "任务延期")
    @PostMapping("/delayTask")
    public ResponseResult delayTask(@RequestBody DelayTaskVo delayTaskVo) {
        return flowTaskService.delayTask(delayTaskVo);
    }

    /**
     * 流程环节跳转列表
     *
     * @return
     */
    @ApiOperation(value = "流程环节跳转列表")
    @PostMapping("/skip/list")
    public ResponseResult skipList(@RequestBody TaskSkipVo taskSkipVo) {
        return flowTaskService.getTaskSkipList(taskSkipVo.getProcessInstanceId());
    }

    /**
     * 流程环节跳转
     *
     * @return
     */
    @ApiOperation(value = "流程环节跳转")
    @PostMapping("/skip")
    public ResponseResult skip(@RequestBody @Validated TaskSkipVo taskSkipVo) {
        return flowTaskService.skipTask(taskSkipVo);
    }

    /**
     * 任务回退列表
     *
     * @param baseTaskVo 回退参数
     * @return 任务回退列表
     */
    @ApiOperation(value = "任务回退列表")
    @PostMapping("/rollback/list")
    public ResponseResult rollbackList(@RequestBody BaseTaskVo baseTaskVo) {
        return flowTaskService.getTaskBackList(baseTaskVo.getTaskId());
    }

    /**
     * 任务回退
     *
     * @param taskRollbackVo 回退参数
     * @return 操作结果
     */
    @ApiOperation(value = "任务回退")
    @PostMapping("/rollback")
    public ResponseResult rollback(@RequestBody TaskRollbackVo taskRollbackVo) {
        return ResponseResult.success(flowTaskService.rollback(taskRollbackVo));
    }



    /**
     * 查询待办任务
     *
     * @param flowExecutionQueryVo 查询条件
     * @return
     */
    @ApiOperation(value = "查询待办任务")
    @PostMapping("/todoTask")
    public ResponseResult todoTask(@RequestBody FlowExecutionQueryVo flowExecutionQueryVo) {
        List<FlowExecutionQueryInfo> flowExecutionQueryInfos = flowTaskQueryRepository.todoTasks(flowExecutionQueryVo);
        return ResponseResult.success(flowExecutionQueryInfos)
                .setTotalCount(flowExecutionQueryInfos.size())
                .setPageSize(flowExecutionQueryInfos.size());
    }

    /**
     * 查询历史任务
     *
     * @param flowExecutionQueryVo
     * @return
     */
    @ApiOperation(value = "查询历史任务")
    @PostMapping("/historyTask")
    public ResponseResult historyTask(@RequestBody FlowExecutionQueryVo flowExecutionQueryVo) {
        List<FlowExecutionQueryInfo> flowExecutionQueryInfos = flowTaskQueryRepository.historyTasks(flowExecutionQueryVo);
        return ResponseResult.success(flowExecutionQueryInfos)
                .setTotalCount(flowExecutionQueryInfos.size())
                .setPageSize(flowExecutionQueryInfos.size());
    }

    /**
     * 待办任务已读
     *
     * @param
     * @return
     */
    @ApiOperation(value = "待办任务已读")
    @PostMapping("/todoTaskupdateReadFlag")
    public ResponseResult updateReadFlag(@RequestParam(value = "taskId", required = true) String taskId ,@RequestParam(value = "userCode", required = true) String userCode) {
        flowTaskInstApproverRepository.todoTaskupdateReadFlag(taskId,userCode, TaskReadEnum.READ.getReadFlag());
        return ResponseResult.success() ;
    }

    /**
     * @Description Flow指定一下节点处理人类入口
     * @author Liujinjian
     * @date 2021-10-18
     * @param taskId
     * @return
     */
    @ApiOperation(value = "获取指定一下节点处理人")
    @PostMapping("/getSpecifyTheNodeHandlerTask")
    public ResponseResult getSpecifyTheNodeHandlerTask(@RequestParam(value = "taskId", required = true) String taskId) {
        List<FlowSpecifyTheNodeHandlerTaskQueryInfo> specifyTheNodeHandlerTaskDataList = flowTaskService.getSpecifyTheNodeHandlerTask(taskId);
        return ResponseResult.success(specifyTheNodeHandlerTaskDataList)
                .setTotalCount(specifyTheNodeHandlerTaskDataList.size())
                .setPageSize(specifyTheNodeHandlerTaskDataList.size());
    }

    /**
     * @Description 根据类型和编码获取当前编码下得人员列表信息
     * @author liujinjian
     * @date 2021-11-01
     * @param type
     * @param code
     * @return
     */
    @ApiOperation(value = "根据类型和编码获取当前编码下得人员列表信息")
    @PostMapping("/getCandidateInfoList")
    public  ResponseResult getCandidateInfoList(@RequestParam(value = "type", required = true) String type,
                                                @RequestParam(value = "code", required = true) String code,
                                                @RequestParam(value = "processInstanceId", required = false) String processInstanceId) {
        FlowTaskCandidateDataTypeVo dataTypeVo = null;
        try {
            User user = userRepository.getCurrentUser();
            dataTypeVo = flowTaskService.getChildCandidate(type,code,processInstanceId, user.getUserCode());
        } catch (Exception e) {
            logger.error("getChildCandidate error",e);
            return ResponseResult.fail(ErrorCode.BAD_REQUEST.errCode(),e.getMessage());
        }
        return ResponseResult.success(dataTypeVo);
    }

    /**
     * @Description 根据实例ID和节点编码获取当前节点候选人对象
     * @author liujinjian
     * @date 2021-11-11
     * @param processInstanceId
     * @param nodeCode
     * @return
     */
    @ApiOperation(value = "根据实例ID和节点编码获取流程处理人信息列表")
    @PostMapping("/getCurrentNodeCandidateInfoList")
    public ResponseResult<FlowSpecifyTheNodeHandlerTaskQueryInfo> getCurrentNodeCandidateInfoList(@RequestParam(value = "processInstanceId", required = true) String processInstanceId,
                                                      @RequestParam(value = "nodeCode", required = true) String nodeCode) {
        FlowSpecifyTheNodeHandlerTaskQueryInfo candidateInfo = null;
        try {
            candidateInfo = flowTaskService.getCurrentNodeCandidateInfo(processInstanceId,nodeCode);
        } catch (Exception e) {
            logger.error("getCurrentNodeCandidateInfo error",e);
            return ResponseResult.fail(ErrorCode.BAD_REQUEST.errCode(),e.getMessage());
        }
        return ResponseResult.success(candidateInfo);
    }

    /**
     * 批量转办待办任务
     *
     * @param batchTurnTaskVo
     * @return
     */
    @ApiOperation(value = "批量转办待办任务")
    @PostMapping("/batchTurnTasks")
    public ResponseResult batchTurnTasks(@RequestBody @Validated BatchTurnTaskVo batchTurnTaskVo) {
        return flowTaskService.batchTurnTasks(batchTurnTaskVo);
    }
}